package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.base.model.RestResponse;
import com.xuecheng.content.feignclient.media.MediaFileClient;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.model.dto.BindMediaDto;
import com.xuecheng.content.model.dto.SaveTeachplanDto;
import com.xuecheng.content.model.dto.TeachplanDto;
import com.xuecheng.content.model.po.CourseBase;
import com.xuecheng.content.model.po.Teachplan;
import com.xuecheng.content.model.po.TeachplanMedia;
import com.xuecheng.content.service.CourseBaseInfoService;
import com.xuecheng.content.service.TeachplanMediaService;
import com.xuecheng.content.service.TeachplanService;
import com.xuecheng.media.model.po.MediaFiles;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan>
    implements TeachplanService {
    @Autowired
    TeachplanMediaService teachplanMediaService;

    @Autowired
    CourseBaseInfoService courseBaseInfoService;

    @Autowired
    MediaFileClient mediaFileClient;

    /**
     * 查询当前课程的所有课程计划
     * @param courseId
     * @return
     */
    @Override
    public List<TeachplanDto> queryAllTeachplansByCourseId(Long courseId) {
        return this.baseMapper.queryAllTeachplanByCourseId(courseId);
    }

    /**
     * 新增或修改课程计划
     * @param dto
     * @return
     */
    @Override
    public Teachplan saveTeachplan(SaveTeachplanDto dto) {
        //首先判断当前课程计划是否存在，然后根据是否存在从而走新增或修改的逻辑
        //新增的时候要设置好课程计划的orderby，因为页面要根据这个按顺序展示
        Long teachplanId = dto.getId();
        Teachplan teachplan = new Teachplan();
        BeanUtils.copyProperties(dto,teachplan);
        if(teachplanId == null){
            //走新增逻辑
            //首先获取当前兄弟课程计划中，也就是同一个父节点下的最大的orderby
            int max = getMaxOrderby(dto.getCourseId(),dto.getParentid());
            teachplan.setOrderby(max + 1);
            save(teachplan);
        }else{
            //走更新逻辑
            updateById(teachplan);
        }
        return getById(teachplan.getId());
    }

    /**
     * 获取兄弟课程计划中最大的orderby
     * @param courseId
     * @param parentid
     * @return
     */
    private int getMaxOrderby(Long courseId, Long parentid) {
        Integer max = this.baseMapper.getMaxOrderby(courseId, parentid);
        return max == null ? 0 : max;
    }

    /**
     * 上移课程计划
     * @param id
     */
    @Override
    public void moveUp(Long id) {
        //先根据课程计划id查询出其所有兄弟课程计划
        List<Teachplan> list = getListBrother(id);
        for(int i=0;i<list.size();i++){
            Teachplan teachplan = list.get(i);
            if(teachplan.getId().equals(id)){
                if(i != 0){
                    Teachplan last = list.get(i - 1);
                    int lastOrderby = last.getOrderby();
                    int orderby = teachplan.getOrderby();
                    last.setOrderby(orderby);
                    teachplan.setOrderby(lastOrderby);
                }
                break;
            }
        }
        updateBatchById(list);
    }

    /**
     * 下移课程计划
     * @param id
     */
    @Override
    public void moveDown(Long id) {
        //先根据课程计划id查询出其所有兄弟课程计划
        List<Teachplan> list = getListBrother(id);
        for(int i=0;i<list.size();i++){
            Teachplan teachplan = list.get(i);
            if(teachplan.getId().equals(id)){
                if(i != list.size() - 1){
                    Teachplan last = list.get(i + 1);
                    int lastOrderby = last.getOrderby();
                    int orderby = teachplan.getOrderby();
                    last.setOrderby(orderby);
                    teachplan.setOrderby(lastOrderby);
                }
                break;
            }
        }
        updateBatchById(list);
    }

    /**
     * 根据课程计划id查询出其所有兄弟课程计划
     * @param id
     * @return
     */
    private List<Teachplan> getListBrother(Long id) {
        Teachplan teachplan = getById(id);
        return list(new LambdaQueryWrapper<Teachplan>()
                .eq(Teachplan::getCourseId,teachplan.getCourseId())
                .eq(Teachplan::getParentid,teachplan.getParentid())
                .orderByAsc(Teachplan::getOrderby));
    }

    /**
     * 根据id删除课程计划
     * @param id
     */
    @Override
    public void deleteTeachplan(Long id) {
        Teachplan teachplan = getById(id);
        if(teachplan == null){
            XueChengPlusException.cast("课程计划不存在");
        }
        if(teachplan.getGrade() == 1){
            //删除大章节的时候，要将大章节中所有的小章节也删除
            Long courseId = teachplan.getCourseId();
            List<Teachplan> list = list(new LambdaQueryWrapper<Teachplan>()
                    .eq(Teachplan::getParentid,id)
                    .eq(Teachplan::getCourseId, courseId));
            List<Long> ids = list.stream()
                    .map(Teachplan::getId)
                    .collect(Collectors.toList());
            remove(new LambdaQueryWrapper<Teachplan>()
                    .in(Teachplan::getId,ids));
            teachplanMediaService.remove(new LambdaQueryWrapper<TeachplanMedia>()
                    .in(TeachplanMedia::getTeachplanId,ids));
        }else{
            //删除小章节的时候，要将小章节关联的teachplan_media记录也删除
            teachplanMediaService.remove(new LambdaQueryWrapper<TeachplanMedia>()
                    .eq(TeachplanMedia::getTeachplanId,id));
        }
        removeById(id);
    }

    /**
     * 课程计划绑定视频
     * @param companyId
     * @param dto
     * @return
     */
    @Override
    public RestResponse<Boolean> bindMedia(Long companyId, BindMediaDto dto) {
        //首先查出课程计划所属课程的所属机构，以及媒资文件的所属机构，判断
        Long mediaId = dto.getMediaId();
        Long teachplanId = dto.getTeachplanId();
        String mediaFileName = dto.getFileName();
        MediaFiles mediaFiles = mediaFileClient.getById(mediaId);
        if(!companyId.equals(mediaFiles.getCompanyId())){
            return RestResponse.validfail(false,"当前媒资文件不属于本机构");
        }
        Teachplan teachplan = getById(teachplanId);
        CourseBase courseBase = courseBaseInfoService.getById(teachplan.getCourseId());
        if(!companyId.equals(courseBase.getCompanyId())){
            return RestResponse.validfail(false,"当前课程不属于本机构");
        }
        TeachplanMedia teachplanMedia = new TeachplanMedia();
        teachplanMedia.setTeachplanId(teachplanId);
        teachplanMedia.setMediaId(mediaId);
        teachplanMedia.setMediaFilename(mediaFileName);
        teachplanMedia.setCourseId(courseBase.getId());
        teachplanMediaService.save(teachplanMedia);
        return RestResponse.success(true);
    }

    /**
     * 课程计划解绑视频
     * @param companyId
     * @param teachplanId
     * @param mediaId
     * @return
     */
    @Override
    public RestResponse<Boolean> unbindMedia(Long companyId, Long teachplanId, Long mediaId) {
        if(teachplanId == null || mediaId == null){
            return RestResponse.validfail(false,"课程计划id或媒资文件id为空");
        }
        //首先查出课程计划所属课程的所属机构，以及媒资文件的所属机构，判断
        MediaFiles mediaFiles = mediaFileClient.getById(mediaId);
        if(!companyId.equals(mediaFiles.getCompanyId())){
            return RestResponse.validfail(false,"当前媒资文件不属于本机构");
        }
        Teachplan teachplan = getById(teachplanId);
        CourseBase courseBase = courseBaseInfoService.getById(teachplan.getCourseId());
        if(!companyId.equals(courseBase.getCompanyId())){
            return RestResponse.validfail(false,"当前课程不属于本机构");
        }
        //然后删除对应的课程计划视频关系
        teachplanMediaService.remove(new LambdaQueryWrapper<TeachplanMedia>()
                .eq(TeachplanMedia::getTeachplanId,teachplanId)
                .eq(TeachplanMedia::getMediaId,mediaId));
        return RestResponse.success(true);
    }
}
